diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp Binary files differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Binary files differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher.webp Binary files differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp Binary files differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp Binary files differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp Binary files differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg new file mode 100644 index 0000000..3d11f73 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg Binary files differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg new file mode 100644 index 0000000..3d11f73 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/empty.png b/app/src/main/res/mipmap-xxhdpi/empty.png new file mode 100644 index 0000000..6da1138 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/empty.png Binary files differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg new file mode 100644 index 0000000..3d11f73 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/empty.png b/app/src/main/res/mipmap-xxhdpi/empty.png new file mode 100644 index 0000000..6da1138 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/empty.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp Binary files differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg new file mode 100644 index 0000000..3d11f73 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/empty.png b/app/src/main/res/mipmap-xxhdpi/empty.png new file mode 100644 index 0000000..6da1138 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/empty.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp Binary files differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg new file mode 100644 index 0000000..3d11f73 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/empty.png b/app/src/main/res/mipmap-xxhdpi/empty.png new file mode 100644 index 0000000..6da1138 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/empty.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_bottom.png b/app/src/main/res/mipmap-xxhdpi/login_bottom.png new file mode 100644 index 0000000..6a4f010 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_bottom.png Binary files differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg new file mode 100644 index 0000000..3d11f73 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/empty.png b/app/src/main/res/mipmap-xxhdpi/empty.png new file mode 100644 index 0000000..6da1138 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/empty.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_bottom.png b/app/src/main/res/mipmap-xxhdpi/login_bottom.png new file mode 100644 index 0000000..6a4f010 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_bottom.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_casic.png b/app/src/main/res/mipmap-xxhdpi/login_casic.png new file mode 100644 index 0000000..edbe69a --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_casic.png Binary files differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg new file mode 100644 index 0000000..3d11f73 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/empty.png b/app/src/main/res/mipmap-xxhdpi/empty.png new file mode 100644 index 0000000..6da1138 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/empty.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_bottom.png b/app/src/main/res/mipmap-xxhdpi/login_bottom.png new file mode 100644 index 0000000..6a4f010 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_bottom.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_casic.png b/app/src/main/res/mipmap-xxhdpi/login_casic.png new file mode 100644 index 0000000..edbe69a --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_background.png b/app/src/main/res/mipmap-xxhdpi/splash_background.png new file mode 100644 index 0000000..3fcca9d --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_background.png Binary files differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg new file mode 100644 index 0000000..3d11f73 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/empty.png b/app/src/main/res/mipmap-xxhdpi/empty.png new file mode 100644 index 0000000..6da1138 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/empty.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_bottom.png b/app/src/main/res/mipmap-xxhdpi/login_bottom.png new file mode 100644 index 0000000..6a4f010 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_bottom.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_casic.png b/app/src/main/res/mipmap-xxhdpi/login_casic.png new file mode 100644 index 0000000..edbe69a --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_background.png b/app/src/main/res/mipmap-xxhdpi/splash_background.png new file mode 100644 index 0000000..3fcca9d --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_background.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_casic.png b/app/src/main/res/mipmap-xxhdpi/splash_casic.png new file mode 100644 index 0000000..37c7e47 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_casic.png Binary files differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg new file mode 100644 index 0000000..3d11f73 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/empty.png b/app/src/main/res/mipmap-xxhdpi/empty.png new file mode 100644 index 0000000..6da1138 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/empty.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_bottom.png b/app/src/main/res/mipmap-xxhdpi/login_bottom.png new file mode 100644 index 0000000..6a4f010 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_bottom.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_casic.png b/app/src/main/res/mipmap-xxhdpi/login_casic.png new file mode 100644 index 0000000..edbe69a --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_background.png b/app/src/main/res/mipmap-xxhdpi/splash_background.png new file mode 100644 index 0000000..3fcca9d --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_background.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_casic.png b/app/src/main/res/mipmap-xxhdpi/splash_casic.png new file mode 100644 index 0000000..37c7e47 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_logo.png b/app/src/main/res/mipmap-xxhdpi/splash_logo.png new file mode 100644 index 0000000..ac2ba0c --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_logo.png Binary files differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg new file mode 100644 index 0000000..3d11f73 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/empty.png b/app/src/main/res/mipmap-xxhdpi/empty.png new file mode 100644 index 0000000..6da1138 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/empty.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_bottom.png b/app/src/main/res/mipmap-xxhdpi/login_bottom.png new file mode 100644 index 0000000..6a4f010 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_bottom.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_casic.png b/app/src/main/res/mipmap-xxhdpi/login_casic.png new file mode 100644 index 0000000..edbe69a --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_background.png b/app/src/main/res/mipmap-xxhdpi/splash_background.png new file mode 100644 index 0000000..3fcca9d --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_background.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_casic.png b/app/src/main/res/mipmap-xxhdpi/splash_casic.png new file mode 100644 index 0000000..37c7e47 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_logo.png b/app/src/main/res/mipmap-xxhdpi/splash_logo.png new file mode 100644 index 0000000..ac2ba0c --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_logo.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_text.png b/app/src/main/res/mipmap-xxhdpi/splash_text.png new file mode 100644 index 0000000..25684d7 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_text.png Binary files differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg new file mode 100644 index 0000000..3d11f73 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/empty.png b/app/src/main/res/mipmap-xxhdpi/empty.png new file mode 100644 index 0000000..6da1138 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/empty.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_bottom.png b/app/src/main/res/mipmap-xxhdpi/login_bottom.png new file mode 100644 index 0000000..6a4f010 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_bottom.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_casic.png b/app/src/main/res/mipmap-xxhdpi/login_casic.png new file mode 100644 index 0000000..edbe69a --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_background.png b/app/src/main/res/mipmap-xxhdpi/splash_background.png new file mode 100644 index 0000000..3fcca9d --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_background.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_casic.png b/app/src/main/res/mipmap-xxhdpi/splash_casic.png new file mode 100644 index 0000000..37c7e47 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_logo.png b/app/src/main/res/mipmap-xxhdpi/splash_logo.png new file mode 100644 index 0000000..ac2ba0c --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_logo.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_text.png b/app/src/main/res/mipmap-xxhdpi/splash_text.png new file mode 100644 index 0000000..25684d7 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_text.png Binary files differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp Binary files differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg new file mode 100644 index 0000000..3d11f73 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/empty.png b/app/src/main/res/mipmap-xxhdpi/empty.png new file mode 100644 index 0000000..6da1138 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/empty.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_bottom.png b/app/src/main/res/mipmap-xxhdpi/login_bottom.png new file mode 100644 index 0000000..6a4f010 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_bottom.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_casic.png b/app/src/main/res/mipmap-xxhdpi/login_casic.png new file mode 100644 index 0000000..edbe69a --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_background.png b/app/src/main/res/mipmap-xxhdpi/splash_background.png new file mode 100644 index 0000000..3fcca9d --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_background.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_casic.png b/app/src/main/res/mipmap-xxhdpi/splash_casic.png new file mode 100644 index 0000000..37c7e47 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_logo.png b/app/src/main/res/mipmap-xxhdpi/splash_logo.png new file mode 100644 index 0000000..ac2ba0c --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_logo.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_text.png b/app/src/main/res/mipmap-xxhdpi/splash_text.png new file mode 100644 index 0000000..25684d7 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_text.png Binary files differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9126ae3 --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp Binary files differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg new file mode 100644 index 0000000..3d11f73 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/empty.png b/app/src/main/res/mipmap-xxhdpi/empty.png new file mode 100644 index 0000000..6da1138 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/empty.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_bottom.png b/app/src/main/res/mipmap-xxhdpi/login_bottom.png new file mode 100644 index 0000000..6a4f010 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_bottom.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_casic.png b/app/src/main/res/mipmap-xxhdpi/login_casic.png new file mode 100644 index 0000000..edbe69a --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_background.png b/app/src/main/res/mipmap-xxhdpi/splash_background.png new file mode 100644 index 0000000..3fcca9d --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_background.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_casic.png b/app/src/main/res/mipmap-xxhdpi/splash_casic.png new file mode 100644 index 0000000..37c7e47 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_logo.png b/app/src/main/res/mipmap-xxhdpi/splash_logo.png new file mode 100644 index 0000000..ac2ba0c --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_logo.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_text.png b/app/src/main/res/mipmap-xxhdpi/splash_text.png new file mode 100644 index 0000000..25684d7 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_text.png Binary files differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9126ae3 --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..9ba1356 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,23 @@ + + + #1D55C6 + #333333 + #626262 + #F7F7FA + #CCCCCC + #00A000 + #FF0000 + #FF6600 + #FF8078 + #80BBFF + #96E9B5 + #916BFF + + #C0000000 + + + #FEB5A2 + #CDA5FF + #C3EB87 + #FFE1AB + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg new file mode 100644 index 0000000..3d11f73 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/empty.png b/app/src/main/res/mipmap-xxhdpi/empty.png new file mode 100644 index 0000000..6da1138 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/empty.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_bottom.png b/app/src/main/res/mipmap-xxhdpi/login_bottom.png new file mode 100644 index 0000000..6a4f010 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_bottom.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_casic.png b/app/src/main/res/mipmap-xxhdpi/login_casic.png new file mode 100644 index 0000000..edbe69a --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_background.png b/app/src/main/res/mipmap-xxhdpi/splash_background.png new file mode 100644 index 0000000..3fcca9d --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_background.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_casic.png b/app/src/main/res/mipmap-xxhdpi/splash_casic.png new file mode 100644 index 0000000..37c7e47 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_logo.png b/app/src/main/res/mipmap-xxhdpi/splash_logo.png new file mode 100644 index 0000000..ac2ba0c --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_logo.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_text.png b/app/src/main/res/mipmap-xxhdpi/splash_text.png new file mode 100644 index 0000000..25684d7 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_text.png Binary files differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9126ae3 --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..9ba1356 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,23 @@ + + + #1D55C6 + #333333 + #626262 + #F7F7FA + #CCCCCC + #00A000 + #FF0000 + #FF6600 + #FF8078 + #80BBFF + #96E9B5 + #916BFF + + #C0000000 + + + #FEB5A2 + #CDA5FF + #C3EB87 + #FFE1AB + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..27c04dc --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,32 @@ + + + 14sp + 16sp + 18sp + 20sp + 45sp + + + 3dp + 5dp + 7dp + 10dp + 20dp + 30dp + 50dp + 80dp + 100dp + 200dp + + + 1px + + + 56dp + + + 46dp + + + 48px + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg new file mode 100644 index 0000000..3d11f73 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/empty.png b/app/src/main/res/mipmap-xxhdpi/empty.png new file mode 100644 index 0000000..6da1138 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/empty.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_bottom.png b/app/src/main/res/mipmap-xxhdpi/login_bottom.png new file mode 100644 index 0000000..6a4f010 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_bottom.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_casic.png b/app/src/main/res/mipmap-xxhdpi/login_casic.png new file mode 100644 index 0000000..edbe69a --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_background.png b/app/src/main/res/mipmap-xxhdpi/splash_background.png new file mode 100644 index 0000000..3fcca9d --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_background.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_casic.png b/app/src/main/res/mipmap-xxhdpi/splash_casic.png new file mode 100644 index 0000000..37c7e47 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_logo.png b/app/src/main/res/mipmap-xxhdpi/splash_logo.png new file mode 100644 index 0000000..ac2ba0c --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_logo.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_text.png b/app/src/main/res/mipmap-xxhdpi/splash_text.png new file mode 100644 index 0000000..25684d7 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_text.png Binary files differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9126ae3 --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..9ba1356 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,23 @@ + + + #1D55C6 + #333333 + #626262 + #F7F7FA + #CCCCCC + #00A000 + #FF0000 + #FF6600 + #FF8078 + #80BBFF + #96E9B5 + #916BFF + + #C0000000 + + + #FEB5A2 + #CDA5FF + #C3EB87 + #FFE1AB + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..27c04dc --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,32 @@ + + + 14sp + 16sp + 18sp + 20sp + 45sp + + + 3dp + 5dp + 7dp + 10dp + 20dp + 30dp + 50dp + 80dp + 100dp + 200dp + + + 1px + + + 56dp + + + 46dp + + + 48px + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..e3ddd7a --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,5 @@ + + QingDaoSmartWell + 中国航天科工集团 + 未知 + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg new file mode 100644 index 0000000..3d11f73 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/empty.png b/app/src/main/res/mipmap-xxhdpi/empty.png new file mode 100644 index 0000000..6da1138 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/empty.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_bottom.png b/app/src/main/res/mipmap-xxhdpi/login_bottom.png new file mode 100644 index 0000000..6a4f010 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_bottom.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_casic.png b/app/src/main/res/mipmap-xxhdpi/login_casic.png new file mode 100644 index 0000000..edbe69a --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_background.png b/app/src/main/res/mipmap-xxhdpi/splash_background.png new file mode 100644 index 0000000..3fcca9d --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_background.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_casic.png b/app/src/main/res/mipmap-xxhdpi/splash_casic.png new file mode 100644 index 0000000..37c7e47 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_logo.png b/app/src/main/res/mipmap-xxhdpi/splash_logo.png new file mode 100644 index 0000000..ac2ba0c --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_logo.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_text.png b/app/src/main/res/mipmap-xxhdpi/splash_text.png new file mode 100644 index 0000000..25684d7 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_text.png Binary files differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9126ae3 --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..9ba1356 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,23 @@ + + + #1D55C6 + #333333 + #626262 + #F7F7FA + #CCCCCC + #00A000 + #FF0000 + #FF6600 + #FF8078 + #80BBFF + #96E9B5 + #916BFF + + #C0000000 + + + #FEB5A2 + #CDA5FF + #C3EB87 + #FFE1AB + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..27c04dc --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,32 @@ + + + 14sp + 16sp + 18sp + 20sp + 45sp + + + 3dp + 5dp + 7dp + 10dp + 20dp + 30dp + 50dp + 80dp + 100dp + 200dp + + + 1px + + + 56dp + + + 46dp + + + 48px + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..e3ddd7a --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,5 @@ + + QingDaoSmartWell + 中国航天科工集团 + 未知 + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..51a91d1 --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg new file mode 100644 index 0000000..3d11f73 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/empty.png b/app/src/main/res/mipmap-xxhdpi/empty.png new file mode 100644 index 0000000..6da1138 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/empty.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_bottom.png b/app/src/main/res/mipmap-xxhdpi/login_bottom.png new file mode 100644 index 0000000..6a4f010 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_bottom.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_casic.png b/app/src/main/res/mipmap-xxhdpi/login_casic.png new file mode 100644 index 0000000..edbe69a --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_background.png b/app/src/main/res/mipmap-xxhdpi/splash_background.png new file mode 100644 index 0000000..3fcca9d --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_background.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_casic.png b/app/src/main/res/mipmap-xxhdpi/splash_casic.png new file mode 100644 index 0000000..37c7e47 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_logo.png b/app/src/main/res/mipmap-xxhdpi/splash_logo.png new file mode 100644 index 0000000..ac2ba0c --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_logo.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_text.png b/app/src/main/res/mipmap-xxhdpi/splash_text.png new file mode 100644 index 0000000..25684d7 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_text.png Binary files differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9126ae3 --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..9ba1356 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,23 @@ + + + #1D55C6 + #333333 + #626262 + #F7F7FA + #CCCCCC + #00A000 + #FF0000 + #FF6600 + #FF8078 + #80BBFF + #96E9B5 + #916BFF + + #C0000000 + + + #FEB5A2 + #CDA5FF + #C3EB87 + #FFE1AB + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..27c04dc --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,32 @@ + + + 14sp + 16sp + 18sp + 20sp + 45sp + + + 3dp + 5dp + 7dp + 10dp + 20dp + 30dp + 50dp + 80dp + 100dp + 200dp + + + 1px + + + 56dp + + + 46dp + + + 48px + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..e3ddd7a --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,5 @@ + + QingDaoSmartWell + 中国航天科工集团 + 未知 + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..51a91d1 --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..862c02a --- /dev/null +++ b/build.gradle @@ -0,0 +1,26 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +buildscript { + ext.kotlin_version = '1.6.10' + repositories { + maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } + google() + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.6.3' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } + //依赖库 + maven { url 'https://jitpack.io' } + google() + jcenter() + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg new file mode 100644 index 0000000..3d11f73 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/empty.png b/app/src/main/res/mipmap-xxhdpi/empty.png new file mode 100644 index 0000000..6da1138 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/empty.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_bottom.png b/app/src/main/res/mipmap-xxhdpi/login_bottom.png new file mode 100644 index 0000000..6a4f010 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_bottom.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_casic.png b/app/src/main/res/mipmap-xxhdpi/login_casic.png new file mode 100644 index 0000000..edbe69a --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_background.png b/app/src/main/res/mipmap-xxhdpi/splash_background.png new file mode 100644 index 0000000..3fcca9d --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_background.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_casic.png b/app/src/main/res/mipmap-xxhdpi/splash_casic.png new file mode 100644 index 0000000..37c7e47 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_logo.png b/app/src/main/res/mipmap-xxhdpi/splash_logo.png new file mode 100644 index 0000000..ac2ba0c --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_logo.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_text.png b/app/src/main/res/mipmap-xxhdpi/splash_text.png new file mode 100644 index 0000000..25684d7 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_text.png Binary files differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9126ae3 --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..9ba1356 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,23 @@ + + + #1D55C6 + #333333 + #626262 + #F7F7FA + #CCCCCC + #00A000 + #FF0000 + #FF6600 + #FF8078 + #80BBFF + #96E9B5 + #916BFF + + #C0000000 + + + #FEB5A2 + #CDA5FF + #C3EB87 + #FFE1AB + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..27c04dc --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,32 @@ + + + 14sp + 16sp + 18sp + 20sp + 45sp + + + 3dp + 5dp + 7dp + 10dp + 20dp + 30dp + 50dp + 80dp + 100dp + 200dp + + + 1px + + + 56dp + + + 46dp + + + 48px + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..e3ddd7a --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,5 @@ + + QingDaoSmartWell + 中国航天科工集团 + 未知 + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..51a91d1 --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..862c02a --- /dev/null +++ b/build.gradle @@ -0,0 +1,26 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +buildscript { + ext.kotlin_version = '1.6.10' + repositories { + maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } + google() + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.6.3' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } + //依赖库 + maven { url 'https://jitpack.io' } + google() + jcenter() + } +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..831abc7 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,25 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app"s APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Kotlin code style for this project: "official" or "obsolete": +kotlin.code.style=official +# Enables namespacing of each library's R class so that its R class includes only the +# resources declared in the library itself and none from the library's dependencies, +# thereby reducing the size of the R class for that library +android.nonTransitiveRClass=true +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg new file mode 100644 index 0000000..3d11f73 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/empty.png b/app/src/main/res/mipmap-xxhdpi/empty.png new file mode 100644 index 0000000..6da1138 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/empty.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_bottom.png b/app/src/main/res/mipmap-xxhdpi/login_bottom.png new file mode 100644 index 0000000..6a4f010 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_bottom.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_casic.png b/app/src/main/res/mipmap-xxhdpi/login_casic.png new file mode 100644 index 0000000..edbe69a --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_background.png b/app/src/main/res/mipmap-xxhdpi/splash_background.png new file mode 100644 index 0000000..3fcca9d --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_background.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_casic.png b/app/src/main/res/mipmap-xxhdpi/splash_casic.png new file mode 100644 index 0000000..37c7e47 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_logo.png b/app/src/main/res/mipmap-xxhdpi/splash_logo.png new file mode 100644 index 0000000..ac2ba0c --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_logo.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_text.png b/app/src/main/res/mipmap-xxhdpi/splash_text.png new file mode 100644 index 0000000..25684d7 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_text.png Binary files differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9126ae3 --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..9ba1356 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,23 @@ + + + #1D55C6 + #333333 + #626262 + #F7F7FA + #CCCCCC + #00A000 + #FF0000 + #FF6600 + #FF8078 + #80BBFF + #96E9B5 + #916BFF + + #C0000000 + + + #FEB5A2 + #CDA5FF + #C3EB87 + #FFE1AB + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..27c04dc --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,32 @@ + + + 14sp + 16sp + 18sp + 20sp + 45sp + + + 3dp + 5dp + 7dp + 10dp + 20dp + 30dp + 50dp + 80dp + 100dp + 200dp + + + 1px + + + 56dp + + + 46dp + + + 48px + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..e3ddd7a --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,5 @@ + + QingDaoSmartWell + 中国航天科工集团 + 未知 + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..51a91d1 --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..862c02a --- /dev/null +++ b/build.gradle @@ -0,0 +1,26 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +buildscript { + ext.kotlin_version = '1.6.10' + repositories { + maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } + google() + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.6.3' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } + //依赖库 + maven { url 'https://jitpack.io' } + google() + jcenter() + } +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..831abc7 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,25 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app"s APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Kotlin code style for this project: "official" or "obsolete": +kotlin.code.style=official +# Enables namespacing of each library's R class so that its R class includes only the +# resources declared in the library itself and none from the library's dependencies, +# thereby reducing the size of the R class for that library +android.nonTransitiveRClass=true +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..e708b1c --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.jar Binary files differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg new file mode 100644 index 0000000..3d11f73 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/empty.png b/app/src/main/res/mipmap-xxhdpi/empty.png new file mode 100644 index 0000000..6da1138 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/empty.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_bottom.png b/app/src/main/res/mipmap-xxhdpi/login_bottom.png new file mode 100644 index 0000000..6a4f010 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_bottom.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_casic.png b/app/src/main/res/mipmap-xxhdpi/login_casic.png new file mode 100644 index 0000000..edbe69a --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_background.png b/app/src/main/res/mipmap-xxhdpi/splash_background.png new file mode 100644 index 0000000..3fcca9d --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_background.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_casic.png b/app/src/main/res/mipmap-xxhdpi/splash_casic.png new file mode 100644 index 0000000..37c7e47 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_logo.png b/app/src/main/res/mipmap-xxhdpi/splash_logo.png new file mode 100644 index 0000000..ac2ba0c --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_logo.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_text.png b/app/src/main/res/mipmap-xxhdpi/splash_text.png new file mode 100644 index 0000000..25684d7 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_text.png Binary files differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9126ae3 --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..9ba1356 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,23 @@ + + + #1D55C6 + #333333 + #626262 + #F7F7FA + #CCCCCC + #00A000 + #FF0000 + #FF6600 + #FF8078 + #80BBFF + #96E9B5 + #916BFF + + #C0000000 + + + #FEB5A2 + #CDA5FF + #C3EB87 + #FFE1AB + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..27c04dc --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,32 @@ + + + 14sp + 16sp + 18sp + 20sp + 45sp + + + 3dp + 5dp + 7dp + 10dp + 20dp + 30dp + 50dp + 80dp + 100dp + 200dp + + + 1px + + + 56dp + + + 46dp + + + 48px + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..e3ddd7a --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,5 @@ + + QingDaoSmartWell + 中国航天科工集团 + 未知 + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..51a91d1 --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..862c02a --- /dev/null +++ b/build.gradle @@ -0,0 +1,26 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +buildscript { + ext.kotlin_version = '1.6.10' + repositories { + maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } + google() + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.6.3' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } + //依赖库 + maven { url 'https://jitpack.io' } + google() + jcenter() + } +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..831abc7 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,25 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app"s APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Kotlin code style for this project: "official" or "obsolete": +kotlin.code.style=official +# Enables namespacing of each library's R class so that its R class includes only the +# resources declared in the library itself and none from the library's dependencies, +# thereby reducing the size of the R class for that library +android.nonTransitiveRClass=true +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..e708b1c --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.jar Binary files differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..605dd40 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Thu Feb 17 13:26:46 CST 2022 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg new file mode 100644 index 0000000..3d11f73 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/empty.png b/app/src/main/res/mipmap-xxhdpi/empty.png new file mode 100644 index 0000000..6da1138 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/empty.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_bottom.png b/app/src/main/res/mipmap-xxhdpi/login_bottom.png new file mode 100644 index 0000000..6a4f010 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_bottom.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_casic.png b/app/src/main/res/mipmap-xxhdpi/login_casic.png new file mode 100644 index 0000000..edbe69a --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_background.png b/app/src/main/res/mipmap-xxhdpi/splash_background.png new file mode 100644 index 0000000..3fcca9d --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_background.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_casic.png b/app/src/main/res/mipmap-xxhdpi/splash_casic.png new file mode 100644 index 0000000..37c7e47 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_logo.png b/app/src/main/res/mipmap-xxhdpi/splash_logo.png new file mode 100644 index 0000000..ac2ba0c --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_logo.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_text.png b/app/src/main/res/mipmap-xxhdpi/splash_text.png new file mode 100644 index 0000000..25684d7 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_text.png Binary files differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9126ae3 --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..9ba1356 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,23 @@ + + + #1D55C6 + #333333 + #626262 + #F7F7FA + #CCCCCC + #00A000 + #FF0000 + #FF6600 + #FF8078 + #80BBFF + #96E9B5 + #916BFF + + #C0000000 + + + #FEB5A2 + #CDA5FF + #C3EB87 + #FFE1AB + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..27c04dc --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,32 @@ + + + 14sp + 16sp + 18sp + 20sp + 45sp + + + 3dp + 5dp + 7dp + 10dp + 20dp + 30dp + 50dp + 80dp + 100dp + 200dp + + + 1px + + + 56dp + + + 46dp + + + 48px + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..e3ddd7a --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,5 @@ + + QingDaoSmartWell + 中国航天科工集团 + 未知 + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..51a91d1 --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..862c02a --- /dev/null +++ b/build.gradle @@ -0,0 +1,26 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +buildscript { + ext.kotlin_version = '1.6.10' + repositories { + maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } + google() + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.6.3' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } + //依赖库 + maven { url 'https://jitpack.io' } + google() + jcenter() + } +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..831abc7 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,25 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app"s APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Kotlin code style for this project: "official" or "obsolete": +kotlin.code.style=official +# Enables namespacing of each library's R class so that its R class includes only the +# resources declared in the library itself and none from the library's dependencies, +# thereby reducing the size of the R class for that library +android.nonTransitiveRClass=true +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..e708b1c --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.jar Binary files differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..605dd40 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Thu Feb 17 13:26:46 CST 2022 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..4f906e0 --- /dev/null +++ b/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg new file mode 100644 index 0000000..3d11f73 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/empty.png b/app/src/main/res/mipmap-xxhdpi/empty.png new file mode 100644 index 0000000..6da1138 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/empty.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_bottom.png b/app/src/main/res/mipmap-xxhdpi/login_bottom.png new file mode 100644 index 0000000..6a4f010 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_bottom.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_casic.png b/app/src/main/res/mipmap-xxhdpi/login_casic.png new file mode 100644 index 0000000..edbe69a --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_background.png b/app/src/main/res/mipmap-xxhdpi/splash_background.png new file mode 100644 index 0000000..3fcca9d --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_background.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_casic.png b/app/src/main/res/mipmap-xxhdpi/splash_casic.png new file mode 100644 index 0000000..37c7e47 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_logo.png b/app/src/main/res/mipmap-xxhdpi/splash_logo.png new file mode 100644 index 0000000..ac2ba0c --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_logo.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_text.png b/app/src/main/res/mipmap-xxhdpi/splash_text.png new file mode 100644 index 0000000..25684d7 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_text.png Binary files differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9126ae3 --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..9ba1356 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,23 @@ + + + #1D55C6 + #333333 + #626262 + #F7F7FA + #CCCCCC + #00A000 + #FF0000 + #FF6600 + #FF8078 + #80BBFF + #96E9B5 + #916BFF + + #C0000000 + + + #FEB5A2 + #CDA5FF + #C3EB87 + #FFE1AB + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..27c04dc --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,32 @@ + + + 14sp + 16sp + 18sp + 20sp + 45sp + + + 3dp + 5dp + 7dp + 10dp + 20dp + 30dp + 50dp + 80dp + 100dp + 200dp + + + 1px + + + 56dp + + + 46dp + + + 48px + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..e3ddd7a --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,5 @@ + + QingDaoSmartWell + 中国航天科工集团 + 未知 + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..51a91d1 --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..862c02a --- /dev/null +++ b/build.gradle @@ -0,0 +1,26 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +buildscript { + ext.kotlin_version = '1.6.10' + repositories { + maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } + google() + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.6.3' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } + //依赖库 + maven { url 'https://jitpack.io' } + google() + jcenter() + } +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..831abc7 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,25 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app"s APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Kotlin code style for this project: "official" or "obsolete": +kotlin.code.style=official +# Enables namespacing of each library's R class so that its R class includes only the +# resources declared in the library itself and none from the library's dependencies, +# thereby reducing the size of the R class for that library +android.nonTransitiveRClass=true +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..e708b1c --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.jar Binary files differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..605dd40 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Thu Feb 17 13:26:46 CST 2022 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..4f906e0 --- /dev/null +++ b/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..ac1b06f --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60307ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/QingDaoSmartWell.jks b/app/QingDaoSmartWell.jks new file mode 100644 index 0000000..76f8be5 --- /dev/null +++ b/app/QingDaoSmartWell.jks Binary files differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c86566b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 31 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.casic.qd.smartwell" + minSdkVersion 23 + targetSdkVersion 31 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlin { + experimental { + coroutines 'enable' + } + } + buildToolsVersion '30.0.3' +} + +dependencies { + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + //基础依赖库 + implementation 'com.github.AndroidCoderPeng:Android-library:1.6.0' + //Google官方授权框架 + implementation 'pub.devrel:easypermissions:3.0.0' + //腾讯Android UI框架 + implementation 'com.qmuiteam:qmui:2.0.0-alpha10' + implementation 'com.qmuiteam:arch:0.3.1' + //沉浸式状态栏。基础依赖包,必须要依赖 + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + //MVVM+LiveData + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" + implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" + //Kotlin协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + //图片加载框架 + implementation 'com.github.bumptech.glide:glide:4.9.0' + //图片选择框架 + implementation 'io.github.lucksiege:pictureselector:v3.0.4' + //高德地图 + implementation 'com.amap.api:3dmap:7.9.1' + implementation 'com.amap.api:location:5.3.1' + //返回值转换器 + implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + //okhttp3日志拦截器 + implementation 'com.squareup.okhttp3:logging-interceptor:4.6.0' + //网络请求和接口封装 + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' + //官方Json解析库 + implementation 'com.google.code.gson:gson:2.8.6' + //上拉加载下拉刷新 + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' + //图表 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + //轮播图 + implementation 'io.github.youth5201314:banner:2.2.2' + //WebView + implementation 'com.just.agentweb:agentweb-androidx:4.1.4' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9514b2 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt new file mode 100644 index 0000000..8720afe --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/AlarmListAdapter.kt @@ -0,0 +1,76 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.model.AlarmListModel +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton + +class AlarmListAdapter( + context: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private var layoutInflater: LayoutInflater = LayoutInflater.from(context) + + override fun onCreateViewHolder( + parent: ViewGroup, viewType: Int + ): AlarmListAdapter.ItemViewHolder { + return ItemViewHolder( + layoutInflater.inflate(R.layout.item_alarm_recycleview, parent, false) + ) + } + + override fun getItemCount(): Int = dataRows.size + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + //绑定数据 + val rowsBean = dataRows[position] + holder.alarmMessageView.text = rowsBean.alarmMessage + val alarmValue = rowsBean.alarmValue.toString() + if (alarmValue.isBlank()) { + holder.alarmValueView.text = "报警值未知" + } else { + holder.alarmValueView.text = alarmValue + } + holder.wellCodeView.text = rowsBean.wellCode + holder.devCodeView.text = rowsBean.devcode + holder.wellLocationView.text = rowsBean.position + holder.createTimeView.text = rowsBean.alarmTime + //绑定事件 + if (listener != null) { + holder.itemView.setOnClickListener { + listener!!.onClicked(position) + } + holder.operationButton.setChangeAlphaWhenPress(true) + holder.operationButton.setOnClickListener { + listener!!.onOperationClicked(position) + } + } + } + + inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { + var alarmMessageView: TextView = view.findViewById(R.id.alarmMessageView) + var alarmValueView: TextView = view.findViewById(R.id.alarmValueView) + var wellCodeView: TextView = view.findViewById(R.id.wellCodeView) + var devCodeView: TextView = view.findViewById(R.id.devCodeView) + var wellLocationView: TextView = view.findViewById(R.id.wellLocationView) + var createTimeView: TextView = view.findViewById(R.id.createTimeView) + var operationButton: QMUIRoundButton = view.findViewById(R.id.operationButton) + } + + private var listener: OnItemClickListener? = null + + interface OnItemClickListener { + fun onClicked(position: Int) + + fun onOperationClicked(position: Int) + } + + fun setOnItemClickListener(onClickListener: OnItemClickListener?) { + this.listener = onClickListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt new file mode 100644 index 0000000..8ff874a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/adapter/HomeRecycleAdapter.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.utils.Constant + +class HomeRecycleAdapter(private val context: Context) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val view: View = + LayoutInflater.from(context).inflate(R.layout.item_home_recycleview, parent, false) + return ItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + holder.imageView.setBackgroundResource(Constant.HOME_ICONS[position]) + holder.textView.text = Constant.HOME_ITEMS[position] + if (clickListener != null) { + holder.itemView.setOnClickListener { + clickListener!!.onClick(position) + } + } + } + + override fun getItemCount(): Int = Constant.HOME_ITEMS.size + + private var clickListener: OnGridItemClickListener? = null + + interface OnGridItemClickListener { + fun onClick(position: Int) + } + + fun setOnGridItemClickListener(onGridItemClickListener: OnGridItemClickListener?) { + clickListener = onGridItemClickListener + } + + class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val imageView: ImageView = itemView.findViewById(R.id.imageView) + val textView: TextView = itemView.findViewById(R.id.textView) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt new file mode 100644 index 0000000..6655804 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseActivity.kt @@ -0,0 +1,75 @@ +package com.casic.qd.smartwell.base + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.extensions.isNetworkConnected +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.PageNavigationManager +import com.casic.qd.smartwell.utils.StatusBarColorUtil +import com.gyf.immersionbar.ImmersionBar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel + +/** + * 普通页面的基础类 + * */ +abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (this.javaClass.simpleName == "SplashScreenActivity" || this.javaClass.simpleName == "LoginActivity") { + //闪屏页和登录页不做网络判断 + setupPage() + } else { + if (this.isNetworkConnected()) { + setupPage() + } else { + "网络好像走丢了~".show() + setContentView(R.layout.page_empty) + } + } + PageNavigationManager.addActivity(this) + } + + private fun setupPage() { + setContentView(initLayoutView()) + ImmersionBar.with(this).statusBarDarkFont(false).init() //沉浸式状态栏 + if (this.javaClass.simpleName != "SplashScreenActivity" && this.javaClass.simpleName != "LoginActivity") { + StatusBarColorUtil.setColor(this, R.color.mainThemeColor.convertColor()) + } + setupTopBarLayout() + initData() + initEvent() + } + + /** + * 初始化xml布局 + */ + abstract fun initLayoutView(): Int + + /** + * 特定页面定制沉浸式状态栏 + */ + protected abstract fun setupTopBarLayout() + + /** + * 初始化默认数据 + */ + abstract fun initData() + + /** + * 初始化业务逻辑 + */ + abstract fun initEvent() + + /** + * 取消协程 + * */ + override fun onDestroy() { + cancel() + super.onDestroy() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt new file mode 100644 index 0000000..f7ebc55 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseApplication.kt @@ -0,0 +1,20 @@ +package com.casic.qd.smartwell.base + +import android.app.Application +import com.casic.qd.smartwell.utils.SaveKeyValues +import kotlin.properties.Delegates + +class BaseApplication : Application() { + + companion object { + private var instance: BaseApplication by Delegates.notNull() + + fun obtainInstance() = instance + } + + override fun onCreate() { + super.onCreate() + instance = this + SaveKeyValues.initSharedPreferences() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt new file mode 100644 index 0000000..2d8ce49 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/base/BaseViewModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.casic.qd.smartwell.utils.LoadState + +abstract class BaseViewModel : ViewModel() { + val loadState = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt new file mode 100644 index 0000000..ab62dc8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Context.kt @@ -0,0 +1,51 @@ +package com.casic.qd.smartwell.extensions + +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant + +/** + * 判断是否有网络连接 + * @return + */ +fun Context.isNetworkConnected(): Boolean { //true是连接,false是没连接 + val manager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager? + if (manager == null) { + return false + } else { + val netWorkInfo = manager.activeNetworkInfo + if (netWorkInfo != null) { + return netWorkInfo.isAvailable + } + } + return false +} + +fun Context.navigatePageTo(clazz: Class) { + startActivity(Intent(this, clazz)) +} + +fun Context.navigatePageTo(clazz: Class, value: String) { + val intent = Intent(this, clazz) + intent.putExtra(Constant.INTENT_PARAM, value) + startActivity(intent) +} + +fun Context.navigatePageTo(clazz: Class, values: ArrayList) { + val intent = Intent(this, clazz) + intent.putStringArrayListExtra(Constant.INTENT_PARAM, values) + startActivity(intent) +} + +fun Context.navigatePageTo( + clazz: Class, + index: Int, + imageList: ArrayList +) { + val intent = Intent(this, clazz) + intent.putExtra("index", index) + intent.putStringArrayListExtra("images", imageList) + startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt new file mode 100644 index 0000000..9327e3d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/Int.kt @@ -0,0 +1,16 @@ +package com.casic.qd.smartwell.extensions + +import androidx.core.content.ContextCompat +import com.casic.qd.smartwell.base.BaseApplication +import kotlin.random.Random + +//颜色扩展 +fun Int.convertColor(): Int = ContextCompat.getColor(BaseApplication.obtainInstance(), this) + +//随机数 +fun Int.randomNumber(): Int { + if (this < 100) { + return Random.nextInt(100) + } + return Random.nextInt(this - 100, this + 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt new file mode 100644 index 0000000..4ef137e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/QMUIEmptyView.kt @@ -0,0 +1,12 @@ +package com.casic.qd.smartwell.extensions + +import android.view.View +import com.qmuiteam.qmui.widget.QMUIEmptyView + +fun QMUIEmptyView.showEmptyPage(onButtonClickListener: View.OnClickListener) { + this.show(false, "抱歉,无法查询到相关记录", null, "重试", onButtonClickListener) +} + +fun QMUIEmptyView.showEmptyPage(title: String, onButtonClickListener: View.OnClickListener) { + this.show(false, title, null, "刷新", onButtonClickListener) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt new file mode 100644 index 0000000..8870765 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/String.kt @@ -0,0 +1,52 @@ +package com.casic.qd.smartwell.extensions + +import android.graphics.Color +import android.view.Gravity +import android.widget.TextView +import android.widget.Toast +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.model.ErrorMessageModel +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.qmuiteam.qmui.util.QMUIDisplayHelper +import org.json.JSONObject + +/** + * String扩展方法 + */ + +//将Toast扩展到String +fun String.show() { + val context = BaseApplication.obtainInstance() + val toast = Toast(context) + val textView = TextView(context) + textView.setBackgroundResource(R.drawable.bg_toast_layout) + textView.setTextColor(Color.WHITE) + textView.textSize = 16.0f + textView.text = this + textView.setPadding( + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10), + QMUIDisplayHelper.dp2px(context, 20), + QMUIDisplayHelper.dp2px(context, 10) + ) + toast.setGravity(Gravity.BOTTOM, 0, QMUIDisplayHelper.dp2px(context, 80)) + toast.view = textView + toast.duration = Toast.LENGTH_SHORT + toast.show() +} + +fun String.separateResponseCode(): Int { + if (this.isBlank()) { + return 404 + } + return JSONObject(this).getInt("code") +} + +fun String.toErrorMessage(): String { + val errorModel = Gson().fromJson( + this, object : TypeToken() {}.type + ) + return errorModel.message.toString() +} diff --git a/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt new file mode 100644 index 0000000..80ec161 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/extensions/ViewModel.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.extensions + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * ViewModel扩展方法:启动协程 + * @param block 协程逻辑 + * @param onError 错误回调方法 + * @param onComplete 完成回调方法 + */ +fun ViewModel.launch( + block: suspend CoroutineScope.() -> Unit, + onError: (e: Throwable) -> Unit = {}, + onComplete: () -> Unit = {} +) { + viewModelScope.launch( + CoroutineExceptionHandler { _, throwable -> + run { + onError(throwable) + } + } + ) { + try { + block.invoke(this) + } finally { + onComplete() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt new file mode 100644 index 0000000..de1293f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/AlarmListModel.kt @@ -0,0 +1,38 @@ +package com.casic.qd.smartwell.model + +class AlarmListModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var rows: MutableList? = null + var total = 0 + + class RowsBean { + var alarmContent = 0 + var deptName: String? = null + var jobStatus: String? = null + var alarmContentName: String? = null + var wellCode: String? = null + var alarmTime: String? = null + var deptid: String? = null + var alarmTypeName: String? = null + var alarmMessage: String? = null + var staff: String? = null + var deviceId: String? = null + var jobId: String? = null + var alarmType: String? = null + var alarmValue: String? = null + var devcode: String? = null + var statusName: String? = null + var alarmLevel: String? = null + var tel: String? = null + var id: String? = null + var wellId: String? = null + var position: String? = null + var status: String? = null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt new file mode 100644 index 0000000..d6af0f1 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/BannerImageModel.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.model + +/** + * @author Administrator + * @description TODO + * @package com.example.mutidemo.bean + * @date 2022/2/17 23:43 + * @email 290677893@qq.com + */ +class BannerImageModel { + /** + * success : true + * code : 200 + * message : 请求成功 + * data : [{"imageTitle":"测试标题1","imageLink":"https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题2","imageLink":"https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题3","imageLink":"https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题4","imageLink":"https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"},{"imageTitle":"测试标题5","imageLink":"https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"}] + */ + var isSuccess = false + var code = 0 + var message: String? = null + var data: List? = null + + class DataBean { + /** + * imageTitle : 测试标题1 + * imageLink : https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500 + */ + var imageTitle: String? = null + var imageLink: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt new file mode 100644 index 0000000..554e513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/ErrorMessageModel.kt @@ -0,0 +1,9 @@ +package com.casic.qd.smartwell.model + +class ErrorMessageModel { + var code = 0 + var data: String? = null + var exceptionClazz: String? = null + var message: String? = null + var isSuccess = false +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt new file mode 100644 index 0000000..c92507a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/LoginResultModel.kt @@ -0,0 +1,13 @@ +package com.casic.qd.smartwell.model + +class LoginResultModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var kaptcha: String? = null + var token: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt new file mode 100644 index 0000000..251b59e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/PublicKeyModel.kt @@ -0,0 +1,18 @@ +package com.casic.qd.smartwell.model + +/** + * PublicKey 登录校验Key + */ +class PublicKeyModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var isAppKaptcha = false + var isKaptcha = false + var publicKey: String? = null + var sid: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt new file mode 100644 index 0000000..56c2e88 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/UserDetailModel.kt @@ -0,0 +1,31 @@ +package com.casic.qd.smartwell.model + +class UserDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var account: String? = null + var attr1: String? = null + var avatar: String? = null + var bizData: String? = null + var dataScope: List? = null + var deptId: String? = null + var deptName: String? = null + var devices: List? = null + var id: String? = null + var ipAddr: String? = null + var name: String? = null + var phone: String? = null + var roleList: List? = null + var roleNames: List? = null + var roleTips: List? = null + var scopeType: String? = null + var sysData: String? = null + var targetId: String? = null + var targetName: String? = null + var tenantId: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt new file mode 100644 index 0000000..10fb21f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/model/WellDetailModel.kt @@ -0,0 +1,41 @@ +package com.casic.qd.smartwell.model + +class WellDetailModel { + var code = 0 + var data: DataBean? = null + var message: String? = null + var isSuccess = false + + class DataBean { + var area: String? = null + var areaFullName: String? = null + var bfzt: String? = null + var bfztName: String? = null + var coordinateX: String? = null + var coordinateY: String? = null + var deep: String? = null + var deptName: String? = null + var deptid: String? = null + var deviceCount: String? = null + var id: String? = null + var latBaidu: String? = null + var latGaode: String? = null + var lngBaidu: String? = null + var lngGaode: String? = null + var notes: String? = null + var photos: String? = null + var position: String? = null + var qu: String? = null + var responsibleDept: String? = null + var responsibleDeptName: String? = null + var ts: String? = null + var valid: String? = null + var wellCode: String? = null + var wellFlag1: String? = null + var wellFlag2: String? = null + var wellFlag3: String? = null + var wellName: String? = null + var wellType: String? = null + var wellTypeName: String? = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt new file mode 100644 index 0000000..e46ad9d --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/AuthenticationHelper.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +object AuthenticationHelper { + + fun savePublicKey(key: String) { + SaveKeyValues.putValue("keyString", key) + } + + val publicKey: String? + get() = SaveKeyValues.getValue("keyString", "") as String? + + fun saveToken(token: String?) { + SaveKeyValues.putValue("token", token!!) + } + + val token: String? + get() = SaveKeyValues.getValue("token", "") as String? + + fun removeToken() { + SaveKeyValues.removeKey("token") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt new file mode 100644 index 0000000..396877c --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/ChartViewHelper.kt @@ -0,0 +1,326 @@ +package com.casic.qd.smartwell.utils + +import android.graphics.Color +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseApplication +import com.casic.qd.smartwell.extensions.convertColor +import com.casic.qd.smartwell.widgets.DetailsMarkerView +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.HorizontalBarChart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.* +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import java.text.DecimalFormat + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @package com.casic.dcms.utils + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val Tag = "ChartViewHelper" + private val decimalFormat = DecimalFormat("##0") + + fun initLineChart(chart: LineChart, axisMaximum: Float) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + chart.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.axisMaximum = axisMaximum + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + chart.description.isEnabled = false + //设置图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + //添加自定义Marker + val detailsMarkerView = DetailsMarkerView(BaseApplication.obtainInstance()) + detailsMarkerView.chartView = chart + chart.marker = detailsMarkerView + } + + fun setLineChartData( + chart: LineChart, + data1Entries: List?, + data2Entries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(data1Entries, "数据1") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(data2Entries, "数据2") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun setLineChartData( + chart: LineChart, + valveEntries: List?, + meterEntries: List?, + pipelineEntries: List?, + deviceEntries: List? + ) { + val lineDataSets: MutableList = ArrayList() + //设置数据 + val valveDataSet = LineDataSet(valveEntries, "阀门") + valveDataSet.color = + R.color.mainThemeColor.convertColor() //线条颜色 + valveDataSet.setCircleColor(R.color.mainThemeColor.convertColor()) //圆点颜色 + valveDataSet.setDrawFilled(true) + valveDataSet.fillColor = + R.color.mainThemeColor.convertColor() + valveDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(valveDataSet) + + val meterDataSet = LineDataSet(meterEntries, "水表") + meterDataSet.color = + R.color.onLineColor.convertColor() //线条颜色 + meterDataSet.setCircleColor(R.color.onLineColor.convertColor()) //圆点颜色 + meterDataSet.setDrawFilled(true) + meterDataSet.fillColor = + R.color.onLineColor.convertColor() + meterDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(meterDataSet) + + val pipelineDataSet = LineDataSet(pipelineEntries, "管线") + pipelineDataSet.color = + R.color.pieColor5.convertColor() //线条颜色 + pipelineDataSet.setCircleColor(R.color.pieColor5.convertColor()) //圆点颜色 + pipelineDataSet.setDrawFilled(true) + pipelineDataSet.fillColor = + R.color.pieColor5.convertColor() + pipelineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(pipelineDataSet) + + val deviceDataSet = LineDataSet(deviceEntries, "噪声仪") + deviceDataSet.color = + R.color.barChartColor.convertColor() //线条颜色 + deviceDataSet.setCircleColor(R.color.barChartColor.convertColor()) //圆点颜色 + deviceDataSet.setDrawFilled(true) + deviceDataSet.fillColor = + R.color.barChartColor.convertColor() + deviceDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(deviceDataSet) + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + chart.data = lineData + chart.invalidate() + } + + fun initBarChart(chart: BarChart) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //图例 + val legend = chart.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = + Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = Constant.BAR_LABEL_NAME.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return Constant.BAR_LABEL_NAME[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: BarChart, last: List, current: List) { + val barDataSets: MutableList = ArrayList() + //绑定数据 + val lastDataSet = BarDataSet(last, "上月") + lastDataSet.color = R.color.barChartColor.convertColor() + lastDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(lastDataSet) + + val currentDataSet = BarDataSet(current, "本月") + currentDataSet.color = R.color.onLineColor.convertColor() + currentDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + barDataSets.add(currentDataSet) + + val barData = BarData(barDataSets) + barData.barWidth = 0.3f + + chart.data = barData + chart.invalidate() + } + + fun initBarChart(chart: HorizontalBarChart, labelName: Array) { + chart.setDrawGridBackground(false) + chart.setDrawBorders(false) + chart.setScaleEnabled(false) + //去掉描述 + chart.description.isEnabled = false + //去掉图例 + chart.legend.isEnabled = false + val xAxis: XAxis = chart.xAxis + xAxis.textColor = R.color.mainTextColor.convertColor() + xAxis.textSize = 12f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = labelName.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return labelName[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + chart.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = chart.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = chart.axisLeft + leftAxis.axisMinimum = 0f + } + + fun setBarChartData(chart: HorizontalBarChart, entries: List?) { + //绑定数据 + val barDataSet = BarDataSet(entries, "") + barDataSet.color = R.color.barChartColor.convertColor() + barDataSet.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + } + } + val barData = BarData(barDataSet) + barData.barWidth = 0.5f + chart.data = barData + chart.invalidate() + } + + fun initPieChart(chart: PieChart) { + chart.setUsePercentValues(false) //百分比数字显示 + chart.description.isEnabled = false + chart.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + chart.setBackgroundColor(Color.WHITE) //设置图表背景色 + chart.rotationAngle = 0f + chart.isRotationEnabled = true + chart.isHighlightPerTapEnabled = true + chart.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + chart.setDrawEntryLabels(false) //不显示分类标签 + chart.isDrawHoleEnabled = true //圆环显示 + chart.setDrawCenterText(true) //圆环中心颜色 + chart.centerText = "分区水表统计" + chart.setEntryLabelColor(Color.BLUE) //图表文本字体颜色 + chart.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + chart.setExtraOffsets(13f, 13f, 13f, 13f) + //设置图例位置 + val legend = chart.legend + legend.verticalAlignment = + Legend.LegendVerticalAlignment.CENTER + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.LEFT + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.formSize = 12f + legend.formToTextSpace = 8f + legend.textSize = 12f + } + + fun setPieChartData(chart: PieChart, entries: List) { + val dataSet = PieDataSet(entries, "") + dataSet.sliceSpace = 3f //设置饼状块之间的间隙 + dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 + //设置饼图块颜色 + val colors: MutableList = ArrayList() + for (i in entries.indices) { + colors.add( + Constant.PIE_COLORS[i].convertColor() + ) + } + dataSet.colors = colors + //设置标签显示在饼图块外面 + dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE + dataSet.valueLineColor = Color.BLUE + dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 + dataSet.valueLinePart2Length = 0.55f //标签指示线后半截长度 + val data = PieData(dataSet) + data.setValueFormatter(object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return decimalFormat.format(value.toDouble()) + "m³" + } + }) + data.setValueTextSize(12f) + data.setValueTextColor(Color.BLUE) //数据值颜色 + chart.data = data + chart.highlightValues(null) + chart.invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt new file mode 100644 index 0000000..e1c1838 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/Constant.kt @@ -0,0 +1,40 @@ +package com.casic.qd.smartwell.utils + +import android.Manifest +import com.casic.qd.smartwell.R + + +object Constant { + val USER_PERMISSIONS = arrayOf( + Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + ) + + const val PERMISSIONS_CODE = 999 + const val PAGE_LIMIT = 20 + + val HOME_ICONS = arrayOf( + R.drawable.ic_home_map, R.drawable.ic_home_record, R.drawable.ic_home_statistics, + ) + val HOME_ITEMS = arrayOf("地图展示", "记录查询", "汇总统计") + + //饼图预置颜色,前三种作为街道统计饼图颜色 + val PIE_COLORS = arrayOf( + R.color.pieColor3, R.color.onLineColor, R.color.pieColor1, + R.color.barChartColor, R.color.punishColor, R.color.colorAccent, + R.color.persuadeColor, R.color.pieColor2, R.color.pieColor5, + R.color.weChatGreen + ) + + val YEARS = arrayOf(2018, 2019, 2020, 2021, 2022) + val BAR_LABEL_NAME = arrayOf( + "10mm", "20mm", "30mm", + "40mm", "50mm", "60mm" + ) + + const val INTENT_PARAM = "intentParam" + const val DEFAULT_SERVER_CONFIG = "defaultServerConfig" + const val ACCOUNT = "account" + const val PASSWORD = "password" + const val USER_DETAIL_MODEL = "userDetailModel" +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt new file mode 100644 index 0000000..465c110 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/DialogHelper.kt @@ -0,0 +1,24 @@ +package com.casic.qd.smartwell.utils; + +import android.content.Context +import com.qmuiteam.qmui.widget.dialog.QMUITipDialog + +object DialogHelper { + private var loadingDialog: QMUITipDialog? = null + + fun showLoadingDialog(context: Context?, message: String?) { + loadingDialog = QMUITipDialog.Builder(context) + .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) + .setTipWord(message) + .create() + loadingDialog!!.show() + } + + fun dismissLoadingDialog() { + if (loadingDialog != null) { + if (loadingDialog!!.isShowing) { + loadingDialog!!.dismiss() + } + } + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt new file mode 100644 index 0000000..1d26ffc --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/LoadState.kt @@ -0,0 +1,22 @@ +package com.casic.qd.smartwell.utils + +/** + * 加载状态 + * sealed 关键字表示此类仅内部继承 + */ +sealed class LoadState { + /** + * 加载中 + */ + object Loading : LoadState() + + /** + * 成功 + */ + object Success : LoadState() + + /** + * 失败 + */ + object Fail : LoadState() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt new file mode 100644 index 0000000..9599d46 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/PageNavigationManager.kt @@ -0,0 +1,70 @@ +package com.casic.qd.smartwell.utils + +import android.app.Activity +import java.util.* + +/** + * 统一管理所有Activity + * */ +object PageNavigationManager { + private var activityStack = Stack() + + /** + * 添加Activity到堆栈 + */ + fun addActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.push(activity) + } + + /** + * 获取当前Activity(堆栈中最后一个压入的) + */ + fun currentActivity(): Activity? { + return activityStack.lastElement() + } + + /** + * 结束当前Activity(堆栈中最后一个压入的) + */ + fun finishCurrentActivity() { + val activity = activityStack.pop() + activity.finish() + } + + /** + * 结束指定的Activity + */ + private fun finishActivity(activity: Activity?) { + if (activity == null) { + return + } + activityStack.remove(activity) + if (!activity.isFinishing) { + activity.finish() + } + } + + /** + * 结束指定类名的Activity + */ + fun finishActivity(clazz: Class) { + activityStack.forEach { + if (it.javaClass == clazz) { + finishActivity(it) + } + } + } + + /** + * 结束所有Activity + */ + fun finishAllActivity() { + activityStack.forEach { + it?.finish() + } + activityStack.clear() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt new file mode 100644 index 0000000..66861bb --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/RSAUtils.kt @@ -0,0 +1,58 @@ +package com.casic.qd.smartwell.utils + +import android.util.Base64 +import java.security.* +import java.security.spec.InvalidKeySpecException +import java.security.spec.X509EncodedKeySpec +import javax.crypto.BadPaddingException +import javax.crypto.Cipher +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException + +object RSAUtils { + //构建Cipher实例时所传入的的字符串,默认为"RSA/NONE/PKCS1Padding" + private fun processData(srcData: ByteArray, key: Key): ByteArray? { //用来保存处理结果 + var resultBytes: ByteArray? = null + try { //获取Cipher实例 + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + //初始化Cipher,mode指定是加密还是解密,key为公钥或私钥 + cipher.init(Cipher.ENCRYPT_MODE, key) + //处理数据 + resultBytes = cipher.doFinal(srcData) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: NoSuchPaddingException) { + e.printStackTrace() + } catch (e: InvalidKeyException) { + e.printStackTrace() + } catch (e: BadPaddingException) { + e.printStackTrace() + } catch (e: IllegalBlockSizeException) { + e.printStackTrace() + } + return resultBytes + } + + fun encryptDataByPublicKey(srcData: ByteArray, publicKey: PublicKey): String { + val resultBytes = + processData(srcData, publicKey) + return Base64.encodeToString(resultBytes, Base64.DEFAULT) + } + + fun keyStrToPublicKey(publicKeyStr: String?): PublicKey? { + var publicKey: PublicKey? = null + val keyBytes = + Base64.decode(publicKeyStr, Base64.DEFAULT) + val keySpec = + X509EncodedKeySpec(keyBytes) + try { + val keyFactory = KeyFactory.getInstance("RSA") + publicKey = keyFactory.generatePublic(keySpec) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } catch (e: InvalidKeySpecException) { + e.printStackTrace() + } + return publicKey + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt new file mode 100644 index 0000000..538fee4 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/SaveKeyValues.kt @@ -0,0 +1,110 @@ +package com.casic.qd.smartwell.utils + +import android.content.Context +import com.casic.qd.smartwell.base.BaseApplication + +object SaveKeyValues { + private val context = BaseApplication.obtainInstance() + private var fileName: String? = null + + fun initSharedPreferences() { + val packageName = context.packageName + //获取到的包名带有“.”方便命名,取最后一个作为sp文件名,例如:com.casic.app.smartwell + val split = packageName.split(".") + fileName = split[split.size - 1] + } + + /** + * 存储 + */ + fun putValue(key: String?, obj: Any) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + val editor = sharedPreferences.edit() + when (obj) { + is String -> { + editor.putString(key, obj).apply() + } + is Int -> { + editor.putInt(key, obj).apply() + } + is Long -> { + editor.putLong(key, obj).apply() + } + is Boolean -> { + editor.putBoolean(key, obj).apply() + } + is Float -> { + editor.putFloat(key, obj).apply() + } + else -> { + editor.putString(key, obj.toString()).apply() + } + } + } + + /** + * 获取保存的数据 + */ + operator fun getValue(key: String?, defaultObject: Any?): Any? { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return when (defaultObject) { + is String -> { + sharedPreferences.getString(key, defaultObject as String?) + } + is Int -> { + sharedPreferences.getInt(key, (defaultObject as Int?)!!) + } + is Long -> { + sharedPreferences.getLong(key, (defaultObject as Long?)!!) + } + is Boolean -> { + sharedPreferences.getBoolean(key, (defaultObject as Boolean?)!!) + } + is Float -> { + sharedPreferences.getFloat(key, (defaultObject as Float?)!!) + } + else -> { + sharedPreferences.getString(key, null) + } + } + } + + /** + * 移除某个key值已经对应的值 + */ + fun removeKey(key: String?) { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().remove(key).apply() + } + + /** + * 清除所有数据 + */ + fun clearAll() { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + sharedPreferences.edit().clear().apply() + } + + /** + * 查询某个key是否存在 + */ + fun containsKey(key: String?): Boolean { + val sharedPreferences = context.getSharedPreferences( + fileName, + Context.MODE_PRIVATE + )!! + return sharedPreferences.contains(key) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt new file mode 100644 index 0000000..52bbc99 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/StatusBarColorUtil.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.utils + +import android.R +import android.app.Activity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.LinearLayout + +object StatusBarColorUtil { + fun setColor(activity: Activity, color: Int) { + //限制android系统的版本 + // 设置状态栏透明 + activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + // 生成一个状态栏大小的矩形 + val statusView = createStatusView(activity, color) + // 添加 statusView 到布局中 + val decorView = activity.window.decorView as ViewGroup + decorView.addView(statusView) + // 设置根布局的参数 + val rootView = + (activity.findViewById(R.id.content) as ViewGroup).getChildAt(0) as ViewGroup + rootView.fitsSystemWindows = true + rootView.clipToPadding = true + } + + /** + * 生成一个和状态栏大小相同的矩形条 + * + * @param activity 需要设置的activity + * @param color 状态栏颜色值 + * @return 状态栏矩形条 + */ + private fun createStatusView(activity: Activity, color: Int): View { + // 获得状态栏高度 + val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android") + val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId) + // 绘制一个和状态栏一样高的矩形 + val statusView = View(activity) + val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight) + statusView.layoutParams = params + statusView.setBackgroundColor(color) + return statusView + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt new file mode 100644 index 0000000..35ca1b0 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/TimeOrDateUtil.kt @@ -0,0 +1,113 @@ +package com.casic.qd.smartwell.utils + +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +/** + * @author : Pengxh + * @time : 2021/4/15 16:54 + * @email : 290677893@qq.com + */ +object TimeOrDateUtil { + private var dateFormat: SimpleDateFormat? = null + + /** + * 获取年月区间,[2022-02-01,2022-02-28] + */ + @Throws(ParseException::class) + fun timestampToMonth(millSeconds: Long): Array { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + //先判断是否在当月 + return if (isInThisMonth(millSeconds)) { + val date = Date() + val calendar = Calendar.getInstance() + calendar.time = date + //获得本月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + date.time = millSeconds + val currentDay = dateFormat!!.format(date) + arrayOf(firstDay, currentDay) + } else { + val dateValue = dateFormat!!.format(Date(millSeconds)) + val date = dateFormat!!.parse(dateValue) + val calendar = Calendar.getInstance() + calendar.time = date + //获得月第一天 + calendar.add(Calendar.MONTH, 0) + calendar[Calendar.DAY_OF_MONTH] = 1 + val firstDay = dateFormat!!.format(calendar.time) + val year = calendar[Calendar.YEAR] + val m = calendar[Calendar.MONTH] + 1 + val month: String = if (m < 10) { + "0$m" + } else { + m.toString() + } + val maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + arrayOf(firstDay, "$year-$month-$maxDay") + } + } + + /** + * 判断时间是否在本月之内 + */ + private fun isInThisMonth(millSeconds: Long): Boolean { + //所选时间对应的月份 + val dateFormat = SimpleDateFormat("MM", Locale.CHINA) + val selectedMonth = dateFormat.format(Date(millSeconds)) + //系统时间对应的月份 + val systemMonth = dateFormat.format(Date(System.currentTimeMillis())) + return selectedMonth == systemMonth + } + + /** + * 时间戳转年月日时分秒 + */ + fun timestampToCompleteDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月日 + */ + fun timestampToDate(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转年月 + */ + fun timestampToYearMonth(millSeconds: Long): String { + dateFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分秒 + */ + fun timestampToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转时分 + */ + fun minuteToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("HH:mm", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } + + /** + * 时间戳转分秒 + */ + fun millsToTime(millSeconds: Long): String { + dateFormat = SimpleDateFormat("mm:ss", Locale.CHINA) + return dateFormat!!.format(Date(millSeconds)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt new file mode 100644 index 0000000..04579cf --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitFactory.kt @@ -0,0 +1,48 @@ +package com.casic.qd.smartwell.utils.retrofit; + +import android.util.Log +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.jetbrains.annotations.NotNull +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.converter.scalars.ScalarsConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitFactory { + private const val kTag = "RetrofitFactory" + + private val httpClient: OkHttpClient by lazy { createOKHttpClient() } + + fun createRetrofit(clazz: Class): T { + val defaultValue = SaveKeyValues.getValue( + Constant.DEFAULT_SERVER_CONFIG, + "http://111.198.10.15:20104" + ) as String + return Retrofit.Builder() + .baseUrl(defaultValue) + .addConverterFactory(ScalarsConverterFactory.create()) //字符串转换器 + .addConverterFactory(GsonConverterFactory.create()) //Gson转换器 + .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke()) //协程请求适配器 + .client(httpClient) //log拦截器 + .build().create(clazz) + } + + private fun createOKHttpClient(): OkHttpClient { //日志显示级别 + val interceptor = + HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { + override fun log(@NotNull message: String) { + Log.d(kTag, ">>>>> $message") + } + }) + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS)// 连接时间:30s超时 + .readTimeout(10, TimeUnit.SECONDS)// 读取时间:10s超时 + .writeTimeout(10, TimeUnit.SECONDS)// 写入时间:10s超时 + return builder.addInterceptor(interceptor).build() + } +} diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt new file mode 100644 index 0000000..4a4d513 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitService.kt @@ -0,0 +1,72 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import retrofit2.http.* + + +/** + * @JvmSuppressWildcards 用来注解类和方法,使得被标记元素的泛型参数不会被编译成通配符 + * */ +@JvmSuppressWildcards +interface RetrofitService { + /** + * PublicKey校验 + */ + @GET("/config/baseConfig") + suspend fun obtainPublicKey(): PublicKeyModel + + /** + * 登录并获取Token + * + * @param sid + * @param account 用户名 + * @param secretKey 加密后的密码 + */ + @FormUrlEncoded + @POST("/user/login") + suspend fun obtainLoginResult( + @Field("sid") sid: String, + @Field("username") account: String, + @Field("password") secretKey: String + ): String + + /** + * 获取用户信息 + */ + @GET("/user/info") + suspend fun obtainUserDetail(@Header("token") token: String): String + + /** + * 用水统计 + */ + @GET("/waterStatistic/overview") + suspend fun waterStatistics(@Header("token") token: String): String + + /** + * 告警列表 + */ + @GET("/alarm/list") + suspend fun obtainAlarmList( + @Header("token") token: String, + @Query("keywords") keywords: String, + @Query("alarmType") alarmType: String, + @Query("areaId") areaId: String, + @Query("alarmContentType") alarmContentType: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("status") status: String, + @Query("offset") offset: Int, + @Query("limit") limit: Int + ): String + + /** + * 获取闸井详情 + * + * @param id 井ID + */ + @GET("/well/info") + suspend fun obtainWellDetail( + @Header("token") token: String, + @Query("id") id: String + ): String +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt new file mode 100644 index 0000000..8679e7b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/utils/retrofit/RetrofitServiceManager.kt @@ -0,0 +1,73 @@ +package com.casic.qd.smartwell.utils.retrofit + +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.AuthenticationHelper +import com.casic.qd.smartwell.utils.Constant + + +object RetrofitServiceManager { + + private val api by lazy { RetrofitFactory.createRetrofit(RetrofitService::class.java) } + + /** + * 验证PublicKey + */ + suspend fun authenticate(): PublicKeyModel { + return api.obtainPublicKey() + } + + /** + * 登录并获取Token + */ + suspend fun login(sid: String, account: String, secretKey: String): String { + return api.obtainLoginResult(sid, account, secretKey) + } + + /** + * 获取用户信息 + */ + suspend fun obtainUserDetail(): String { + return api.obtainUserDetail(AuthenticationHelper.token!!) + } + + /** + * 用水统计 + */ + suspend fun waterStatistics(): String { + return api.waterStatistics(AuthenticationHelper.token!!) + } + + /** + * 告警列表 + */ + suspend fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ): String { + return api.obtainAlarmList( + AuthenticationHelper.token!!, + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page, + Constant.PAGE_LIMIT + ) + } + + /** + * 获取闸井详情 + */ + suspend fun obtainWellDetail(id: String): String { + return api.obtainWellDetail(AuthenticationHelper.token!!, id) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt new file mode 100644 index 0000000..834c00f --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/AlarmManagementActivity.kt @@ -0,0 +1,146 @@ +package com.casic.qd.smartwell.view + +import android.annotation.SuppressLint +import android.os.Handler +import android.os.Looper +import android.os.Message +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.AlarmListAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.showEmptyPage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.vm.AlarmListViewModel +import com.pengxh.app.multilib.widget.dialog.InputDialog +import kotlinx.android.synthetic.main.activity_alarm_management.* +import kotlinx.android.synthetic.main.include_empty_view.* +import java.lang.ref.WeakReference + + +class AlarmManagementActivity : BaseActivity() { + + private lateinit var alarmListViewModel: AlarmListViewModel + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmListAdapter: AlarmListAdapter + private var dataBeans: MutableList = ArrayList() + private var pageIndex = 1 + private var isRefresh = false + private var isLoadMore = false + + override fun initLayoutView(): Int = R.layout.activity_alarm_management + + override fun setupTopBarLayout() { + titleView.text = "当前告警" + } + + override fun initData() { + alarmListViewModel = ViewModelProvider(this).get(AlarmListViewModel::class.java) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + obtainAlarmList(pageIndex) + alarmListViewModel.listModel.observe(this, { + if (it.code == 200) { + val dataRows = it.data?.rows + when { + isRefresh -> { + dataBeans.clear() + dataBeans = dataRows!! + alarmListLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows?.size == 0) { + "到底了,别拉了".show() + } + dataBeans.addAll(dataRows!!) + alarmListLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows!! + } + } + weakReferenceHandler.sendEmptyMessage(2022041301) + } + }) + + alarmListLayout.setOnRefreshListener { + isRefresh = true + //刷新之后页码重置 + pageIndex = 1 + obtainAlarmList(pageIndex) + } + alarmListLayout.setOnLoadMoreListener { + isLoadMore = true + pageIndex++ + obtainAlarmList(pageIndex) + } + } + + private fun obtainAlarmList(pageIndex: Int) { + alarmListViewModel.obtainAlarmList("", "", "", "", "", "", "1", pageIndex) + } + + private class WeakReferenceHandler(activity: AlarmManagementActivity) : + Handler(Looper.getMainLooper()) { + private val reference: WeakReference = WeakReference(activity) + + @SuppressLint("NotifyDataSetChanged") + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + if (msg.what == 2022041301) { + if (activity.isRefresh || activity.isLoadMore) { + activity.alarmListAdapter.notifyDataSetChanged() + } else { //首次加载数据 + if (activity.dataBeans.size == 0) { + activity.emptyView!!.showEmptyPage { + activity.obtainAlarmList(activity.pageIndex) + } + } else { + activity.emptyView!!.hide() + activity.alarmListAdapter = AlarmListAdapter(activity, activity.dataBeans) + activity.alarmListView!!.layoutManager = LinearLayoutManager(activity) + activity.alarmListView!!.adapter = activity.alarmListAdapter + activity.alarmListAdapter.setOnItemClickListener(object : + AlarmListAdapter.OnItemClickListener { + override fun onClicked(position: Int) { + val wellId = activity.dataBeans[position].wellId.toString() + if (wellId.isBlank()) { + "井编号异常,无法查看详情".show() + return + } + activity.navigatePageTo(WellDetailActivity::class.java, wellId) + } + + override fun onOperationClicked(position: Int) { + val wellDetail = activity.dataBeans[position] + InputDialog.Builder() + .setContext(activity) + .setTitle("取消告警") + .setHintMessage("请输入详细的告警取消原因") + .setNegativeButton("无需处理") + .setPositiveButton("已处理") + .setOnDialogButtonClickListener(object : + InputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + //已处理 + } + + override fun onCancelClick() { + //无需处理 + } + }).build().show() + } + }) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt new file mode 100644 index 0000000..526fa73 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/LoginActivity.kt @@ -0,0 +1,134 @@ +package com.casic.qd.smartwell.view + +import android.text.Editable +import android.text.TextWatcher +import android.view.KeyEvent +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.utils.* +import com.casic.qd.smartwell.vm.AuthenticateViewModel +import com.casic.qd.smartwell.vm.LoginInViewModel +import com.casic.qd.smartwell.vm.UserDetailViewModel +import com.qmuiteam.qmui.util.QMUIStatusBarHelper +import kotlinx.android.synthetic.main.activity_login.* + +class LoginActivity : BaseActivity() { + + private lateinit var authenticateViewModel: AuthenticateViewModel + private lateinit var loginInViewModel: LoginInViewModel + private lateinit var userDetailViewModel: UserDetailViewModel + + private val textWatcher = object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable) { + if (s.toString().trim { it <= ' ' }.length > 16) { + inputLayout.error = "密码长度超出限制" + } else { + inputLayout.error = null + } + } + } + + override fun initLayoutView(): Int = R.layout.activity_login + + override fun setupTopBarLayout() { + //设置状态栏黑色字体图标 + QMUIStatusBarHelper.setStatusBarLightMode(this) + } + + override fun initData() { + // 设置默认账号密码 + userNameView.setText(SaveKeyValues.getValue(Constant.ACCOUNT, "") as String) + userPasswordView.setText(SaveKeyValues.getValue(Constant.PASSWORD, "") as String) + authenticateViewModel = ViewModelProvider(this).get(AuthenticateViewModel::class.java) + loginInViewModel = ViewModelProvider(this).get(LoginInViewModel::class.java) + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + val editText: EditText? = inputLayout.editText + editText?.addTextChangedListener(textWatcher) + //点击输入法键盘"完成" + editText?.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? -> + if (actionId == EditorInfo.IME_ACTION_DONE) { + authenticateViewModel.obtainPublicKey() + return@setOnEditorActionListener true + } + false + } + + loginButton.setChangeAlphaWhenPress(true) + loginButton.setOnClickListener { + val account = userNameView.text.toString().trim() + val userPassword = userPasswordView.text.toString().trim() + if (account.isBlank()) { + "用户名不能为空".show() + return@setOnClickListener + } + if (userPassword.isBlank()) { + "密码不能为空".show() + return@setOnClickListener + } + SaveKeyValues.putValue(Constant.ACCOUNT, account) + SaveKeyValues.putValue(Constant.PASSWORD, userPassword) + authenticateViewModel.obtainPublicKey() + } + authenticateViewModel.keyModel.observe(this, { + if (it.code == 200) {//用code判断,别的判断可能有坑 + val keyString = it.data!!.publicKey!! + /** + * 修改密码需要用到key,先存着 + * */ + AuthenticationHelper.savePublicKey(keyString) + val publicKey = RSAUtils.keyStrToPublicKey(keyString) + + val account = userNameView.text.toString() + val userPassword = userPasswordView.text.toString() + val dataByPublicKey = + RSAUtils.encryptDataByPublicKey(userPassword.toByteArray(), publicKey!!) + //登录并获取Token,POST请求 + loginInViewModel.login(it.data!!.sid!!, account, dataByPublicKey) + loginInViewModel.resultModel.observe(this, { loginResult -> + if (loginResult.code == 200) { + AuthenticationHelper.saveToken(loginResult.data!!.token!!) + //获取token之后保存用户信息 + userDetailViewModel.obtainUserDetail() + //验证成功登录 + this.navigatePageTo(MainActivity::class.java) + finish() + } + }) + loginInViewModel.loadState.observe(this, { loginState -> + when (loginState) { + is LoadState.Success -> { + "登录成功".show() + DialogHelper.dismissLoadingDialog() + } + else -> { + "登录失败,用户名或密码错误".show() + DialogHelper.dismissLoadingDialog() + } + } + }) + } else { + it.message!!.show() + } + }) + authenticateViewModel.loadState.observe(this, { + DialogHelper.showLoadingDialog(this, "登录中,请稍后") + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt new file mode 100644 index 0000000..217dd2b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MainActivity.kt @@ -0,0 +1,176 @@ +package com.casic.qd.smartwell.view + +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.KeyEvent +import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.GridLayoutManager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestOptions +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.adapter.HomeRecycleAdapter +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.BannerImageModel +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.TimeOrDateUtil +import com.casic.qd.smartwell.vm.WaterStatisticsViewModel +import com.github.mikephil.charting.data.Entry +import com.youth.banner.Banner +import com.youth.banner.adapter.BannerImageAdapter +import com.youth.banner.holder.BannerImageHolder +import com.youth.banner.indicator.CircleIndicator +import kotlinx.android.synthetic.main.activity_main.* +import java.lang.ref.WeakReference +import java.util.* + +class MainActivity : BaseActivity() { + + private val kTag = "MainActivity" + private val context: Context = this@MainActivity + private var clickTime: Long = 0 + private lateinit var waterViewModel: WaterStatisticsViewModel + + private val data1Entries: ArrayList = ArrayList() + private val data2Entries: ArrayList = ArrayList() + private val imageUrls = listOf( + "https://images.pexels.com/photos/1036808/pexels-photo-1036808.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/796602/pexels-photo-796602.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/1109543/pexels-photo-1109543.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/296115/pexels-photo-296115.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", + "https://images.pexels.com/photos/4158/apple-iphone-smartphone-desk.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500" + ) + private lateinit var weakReferenceHandler: WeakReferenceHandler + + //TODO 测试数据 + private fun getData(): MutableList { + val list = ArrayList() + for (i in 0..4) { + val dataBean: BannerImageModel.DataBean = BannerImageModel.DataBean() + dataBean.imageTitle = "测试图片$i" + dataBean.imageLink = imageUrls[i] + list.add(dataBean) + } + return list + } + + override fun initLayoutView(): Int = R.layout.activity_main + + override fun setupTopBarLayout() { + titleView.text = "智能闸井-青岛地区" + } + + override fun initData() { + //轮播图 + val banner = + (mainBannerView as Banner>) + banner.apply { + addBannerLifecycleObserver(this@MainActivity) + indicator = CircleIndicator(context) + setAdapter(object : BannerImageAdapter(getData()) { + override fun onBindView( + holder: BannerImageHolder, + data: BannerImageModel.DataBean, + position: Int, + size: Int + ) { + Glide.with(holder.itemView) + .load(data.imageLink) + .apply(RequestOptions.bitmapTransform(RoundedCorners(30))) + .into(holder.imageView) + } + }) + //Banner点击事件 + setOnBannerListener { data, _ -> + startActivity(Intent(this@MainActivity, WebsiteActivity::class.java)) + } + } + + //首页功能块 + val homeRecycleAdapter = HomeRecycleAdapter(this) + homeRecyclerView.layoutManager = GridLayoutManager(this, 3) + homeRecyclerView.adapter = homeRecycleAdapter + homeRecycleAdapter.setOnGridItemClickListener(object : + HomeRecycleAdapter.OnGridItemClickListener { + override fun onClick(position: Int) { + when (position) { + 0 -> startActivity(Intent(context, MapActivity::class.java)) + 1 -> startActivity(Intent(context, SearchRecordActivity::class.java)) + 2 -> startActivity(Intent(context, StatisticsActivity::class.java)) + } + } + }) + + //初始化vm + waterViewModel = ViewModelProvider(this).get(WaterStatisticsViewModel::class.java) + + //初始化折线图 + val date = TimeOrDateUtil.timestampToMonth(System.currentTimeMillis()) + val currentDay = date[1].split("-")[2].toInt() + ChartViewHelper.initLineChart(waterLineChart, currentDay.toFloat()) + //TODO 这是模拟数据 + for (i in 1..currentDay) { + data1Entries.add( + Entry( + i.toFloat(), + Random().nextInt(15).toFloat(), "data1" + ) + ) + } + for (i in 1..currentDay) { + data2Entries.add( + Entry( + i.toFloat(), + Random().nextInt(20).toFloat(), "data2" + ) + ) + } + ChartViewHelper.setLineChartData( + waterLineChart, + data1Entries, + data2Entries + ) + weakReferenceHandler = WeakReferenceHandler(this) + } + + override fun initEvent() { + waterViewModel.waterStatistics() + waterViewModel.resultModel.observe(this, { + totalWaterView.text = String.format("${it["total"]}t") + monthWaterView.text = String.format("${it["month"]}t") + todayWaterView.text = String.format("${it["today"]}t") + }) + + rightOptionView.setOnClickListener { + navigatePageTo(AlarmManagementActivity::class.java) + } + } + + private class WeakReferenceHandler(activity: MainActivity) : Handler(Looper.getMainLooper()) { + + private val reference: WeakReference = WeakReference(activity) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val activity = reference.get()!! + + } + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + if (System.currentTimeMillis() - clickTime > 2000) { + "再按一次退出程序".show() + clickTime = System.currentTimeMillis() + true + } else { + super.onKeyDown(keyCode, event) + } + } else super.onKeyDown(keyCode, event) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt new file mode 100644 index 0000000..1dea700 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/MapActivity.kt @@ -0,0 +1,62 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import com.amap.api.maps.AMap +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.activity_map.* +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 地图页面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class MapActivity : BaseActivity() { + + private var aMap: AMap? = null + + override fun initLayoutView(): Int = R.layout.activity_map + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "地图展示" + } + + override fun initData() { + if (aMap == null) { + aMap = mapView.map + } + } + + override fun initEvent() { + + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mapView.onCreate(savedInstanceState) + } + override fun onResume() { + super.onResume() + mapView.onResume() + } + + override fun onPause() { + super.onPause() + mapView.onResume() + } + + override fun onDestroy() { + mapView.onDestroy(); + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapView.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt new file mode 100644 index 0000000..0d23233 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/PermissionActivity.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.PageNavigationManager +import pub.devrel.easypermissions.EasyPermissions +import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks + +class PermissionActivity : AppCompatActivity(), PermissionCallbacks { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PageNavigationManager.addActivity(this) + //判断是否有权限,如果版本大于5.1才需要判断(即6.0以上),其他则不需要判断。 + if (EasyPermissions.hasPermissions(this, *Constant.USER_PERMISSIONS)) { + startSplashScreenActivity() + } else { + EasyPermissions.requestPermissions( + this, + "需要获取相关权限", + Constant.PERMISSIONS_CODE, + *Constant.USER_PERMISSIONS + ) + } + } + + private fun startSplashScreenActivity() { + this.navigatePageTo(SplashScreenActivity::class.java) + finish() + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) + } + + override fun onPermissionsGranted(requestCode: Int, perms: List) { + startSplashScreenActivity() + } + + override fun onPermissionsDenied(requestCode: Int, perms: List) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt new file mode 100644 index 0000000..7f63c0a --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SearchRecordActivity.kt @@ -0,0 +1,30 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import kotlinx.android.synthetic.main.include_base_title.* + +/** + * @author a203 + * @description 记录查询界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:33 + * @email 290677893@qq.com + */ +class SearchRecordActivity : BaseActivity() { + + override fun initLayoutView(): Int = R.layout.activity_search_record + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "记录查询" + } + + override fun initData() { + + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt new file mode 100644 index 0000000..003d39e --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/SplashScreenActivity.kt @@ -0,0 +1,45 @@ +package com.casic.qd.smartwell.view + +import android.os.CountDownTimer +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.extensions.navigatePageTo +import com.casic.qd.smartwell.vm.UserDetailViewModel + +class SplashScreenActivity : BaseActivity() { + + private lateinit var userDetailViewModel: UserDetailViewModel + + override fun initLayoutView(): Int = R.layout.activity_splash + + override fun setupTopBarLayout() { + + } + + override fun initData() { + userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java) + } + + override fun initEvent() { + countDownTimer.start() + } + + private val countDownTimer = object : CountDownTimer(1000, 500) { + override fun onFinish() { + userDetailViewModel.obtainUserDetail() + userDetailViewModel.flag.observe(this@SplashScreenActivity, { + if (it) { + navigatePageTo(MainActivity::class.java) + } else { + navigatePageTo(LoginActivity::class.java) + } + finish() + }) + } + + override fun onTick(millisUntilFinished: Long) { + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt new file mode 100644 index 0000000..f6874f9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/StatisticsActivity.kt @@ -0,0 +1,97 @@ +package com.casic.qd.smartwell.view + +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.ChartViewHelper +import com.casic.qd.smartwell.utils.Constant +import com.github.mikephil.charting.data.BarEntry +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.PieEntry +import kotlinx.android.synthetic.main.activity_statistics.* +import kotlinx.android.synthetic.main.include_base_title.* +import java.util.* + +/** + * @author a203 + * @description 汇总统计界面 + * @package com.casic.qd.smartwell.view + * @date 2022/2/17 14:34 + * @email 290677893@qq.com + */ +class StatisticsActivity : BaseActivity() { + + private val valveEntries: ArrayList = ArrayList() + private val meterEntries: ArrayList = ArrayList() + private val pipelineEntries: ArrayList = ArrayList() + private val deviceEntries: ArrayList = ArrayList() + private val pieEntries: ArrayList = ArrayList() + private val lastMonthEntries: ArrayList = ArrayList() + private val currentMonthEntries: ArrayList = ArrayList() + + override fun initLayoutView(): Int = R.layout.activity_statistics + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "汇总统计" + } + + override fun initData() { + //初始化饼图 + ChartViewHelper.initPieChart(totalPieChart) + //TODO 这是模拟数据 + for (i in 0..4) { + pieEntries.add(PieEntry(Random().nextInt(100).toFloat(), "片区$i")) + } + ChartViewHelper.setPieChartData(totalPieChart, pieEntries) + + //初始化折线图 + ChartViewHelper.initLineChart(totalLineChart, Constant.YEARS.last().toFloat()) + //TODO 这是模拟数据 + for (i in Constant.YEARS) { + valveEntries.add( + Entry( + i.toFloat(), + Random().nextInt(150).toFloat(), "阀门" + ) + ) + meterEntries.add( + Entry( + i.toFloat(), + Random().nextInt(200).toFloat(), "水表" + ) + ) + pipelineEntries.add( + Entry( + i.toFloat(), + Random().nextInt(100).toFloat(), "管线" + ) + ) + deviceEntries.add( + Entry( + i.toFloat(), + Random().nextInt(10).toFloat(), "噪声仪" + ) + ) + } + ChartViewHelper.setLineChartData( + totalLineChart, + valveEntries, + meterEntries, + pipelineEntries, + deviceEntries + ) + + //初始化柱状图 + ChartViewHelper.initBarChart(totalBarChart) + //TODO 这是模拟数据 + for (i in 0..5) { + lastMonthEntries.add(BarEntry((i - 0.15).toFloat(), Random().nextInt(150).toFloat())) + currentMonthEntries.add(BarEntry((i + 0.15).toFloat(), Random().nextInt(150).toFloat())) + } + ChartViewHelper.setBarChartData(totalBarChart, lastMonthEntries, currentMonthEntries) + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt new file mode 100644 index 0000000..d9dbe77 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WebsiteActivity.kt @@ -0,0 +1,33 @@ +package com.casic.qd.smartwell.view + +import android.widget.LinearLayout +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.just.agentweb.AgentWeb +import kotlinx.android.synthetic.main.activity_web.* +import kotlinx.android.synthetic.main.include_base_title.* + +class WebsiteActivity : BaseActivity() { + + private lateinit var agentWeb: AgentWeb + + override fun initLayoutView(): Int = R.layout.activity_web + + override fun setupTopBarLayout() { + leftBackView.setOnClickListener { finish() } + titleView.text = "海洋石油工程有限公司" + } + + override fun initData() { + agentWeb = AgentWeb.with(this) + .setAgentWebParent(containerView, LinearLayout.LayoutParams(-1, -1)) + .useDefaultIndicator() + .createAgentWeb() + .ready() + .go("https://www.cnoocengineering.com") + } + + override fun initEvent() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt new file mode 100644 index 0000000..f1cbb83 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/view/WellDetailActivity.kt @@ -0,0 +1,79 @@ +package com.casic.qd.smartwell.view + +import android.view.View +import androidx.lifecycle.ViewModelProvider +import com.casic.qd.smartwell.R +import com.casic.qd.smartwell.base.BaseActivity +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.DialogHelper +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.vm.WellDetailViewModel +import com.pengxh.app.multilib.widget.dialog.AlertMessageDialog +import kotlinx.android.synthetic.main.activity_well_detail.* +import kotlinx.android.synthetic.main.include_base_title.* + + +class WellDetailActivity : BaseActivity() { + + private lateinit var wellDetailViewModel: WellDetailViewModel + private lateinit var wellId: String + + override fun initLayoutView(): Int = R.layout.activity_well_detail + + override fun setupTopBarLayout() { + titleView.text = "井详情" + leftBackView.visibility = View.GONE + } + + override fun initData() { + wellId = intent.getStringExtra(Constant.INTENT_PARAM)!! + wellDetailViewModel = ViewModelProvider(this).get(WellDetailViewModel::class.java) + } + + override fun initEvent() { + wellDetailViewModel.obtainWellDetail(wellId) + wellDetailViewModel.detailModel.observe(this, { + if (it.code == 200) { + val wellDetail = it.data!! + + wellNameView.text = wellDetail.wellName + wellCodeView.text = wellDetail.wellCode + wellTypeView.text = wellDetail.wellTypeName + ownershipView.text = wellDetail.deptName + val depth = wellDetail.deep.toString() + if (depth.isBlank()) { + wellDepthView.text = resources.getString(R.string.unknown) + } else { + wellDepthView.text = depth + } + wellStateView.text = wellDetail.bfztName + //绑定窨井位置 + val wellPosition = wellDetail.position.toString() + wellLocationView.text = wellPosition + if (wellPosition.length > 12) { + tipsImageView.visibility = View.VISIBLE + tipsImageView.setOnClickListener { + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("闸井完整位置") + .setMessage(wellPosition) + .setPositiveButton("知道了").setOnDialogButtonClickListener {}.build() + .show() + } + } else { + tipsImageView.visibility = View.GONE + } + } + }) + wellDetailViewModel.loadState.observe(this, { + when (it) { + is LoadState.Loading -> { + DialogHelper.showLoadingDialog(this, "数据加载中,请稍后") + } + else -> { + DialogHelper.dismissLoadingDialog() + } + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt new file mode 100644 index 0000000..2f41249 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AlarmListViewModel.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.AlarmListModel +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class AlarmListViewModel : BaseViewModel() { + + private val gson = Gson() + val listModel = MutableLiveData() + + fun obtainAlarmList( + keywords: String, + alarmType: String, + areaId: String, + alarmContentType: String, + beginTime: String, + endTime: String, + status: String, + page: Int + ) = launch({ + val response = RetrofitServiceManager.obtainAlarmList( + keywords, + alarmType, + areaId, + alarmContentType, + beginTime, + endTime, + status, + page + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + listModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt new file mode 100644 index 0000000..6b1d404 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/AuthenticateViewModel.kt @@ -0,0 +1,21 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.PublicKeyModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager + +class AuthenticateViewModel : BaseViewModel() { + + val keyModel = MutableLiveData() + + fun obtainPublicKey() = launch({ + loadState.value = LoadState.Loading + keyModel.value = RetrofitServiceManager.authenticate() + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt new file mode 100644 index 0000000..ec0ac1b --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/LoginInViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.LoginResultModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class LoginInViewModel : BaseViewModel() { + + private val gson = Gson() + val resultModel = MutableLiveData() + + fun login(sid: String, account: String, secretKey: String) = launch({ + val response = RetrofitServiceManager.login(sid, account, secretKey) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt new file mode 100644 index 0000000..5bf6c64 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/UserDetailViewModel.kt @@ -0,0 +1,39 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.model.UserDetailModel +import com.casic.qd.smartwell.utils.Constant +import com.casic.qd.smartwell.utils.SaveKeyValues +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class UserDetailViewModel : BaseViewModel() { + + private val gson = Gson() + + //用户信息不用现取现用,布尔值标志用户token是否失效 + val flag = MutableLiveData() + + fun obtainUserDetail() = launch({ + val response = RetrofitServiceManager.obtainUserDetail() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val userData = gson.fromJson( + response, object : TypeToken() {}.type + ).data + SaveKeyValues.putValue(Constant.USER_DETAIL_MODEL, gson.toJson(userData)) + flag.value = true + } else { + //如果此次获取不到用户信息,那么就清空之前的用户缓存,然后让用户重新登录 + SaveKeyValues.removeKey(Constant.USER_DETAIL_MODEL) + flag.value = false + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt new file mode 100644 index 0000000..7c8ded9 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WaterStatisticsViewModel.kt @@ -0,0 +1,36 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import org.json.JSONObject + +class WaterStatisticsViewModel : BaseViewModel() { + + val resultModel = MutableLiveData>() + + fun waterStatistics() = launch({ + val response = RetrofitServiceManager.waterStatistics() + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + val map = HashMap(5) + + val jsonObject = JSONObject(response) + val data = jsonObject.getJSONObject("data") + map["total"] = data.getString("total") + map["month"] = data.getString("month") + map["today"] = data.getString("today") + map["prodution"] = data.getString("prodution") + map["sound"] = data.getString("sound") + resultModel.value = map + } else { + response.toErrorMessage().show() + } + }, { + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt new file mode 100644 index 0000000..b2bdaaa --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/vm/WellDetailViewModel.kt @@ -0,0 +1,37 @@ +package com.casic.qd.smartwell.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.qd.smartwell.base.BaseViewModel +import com.casic.qd.smartwell.extensions.launch +import com.casic.qd.smartwell.extensions.separateResponseCode +import com.casic.qd.smartwell.extensions.show +import com.casic.qd.smartwell.extensions.toErrorMessage +import com.casic.qd.smartwell.model.WellDetailModel +import com.casic.qd.smartwell.utils.LoadState +import com.casic.qd.smartwell.utils.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +class WellDetailViewModel : BaseViewModel() { + + private val gson = Gson() + val detailModel = MutableLiveData() + + fun obtainWellDetail(id: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.obtainWellDetail(id) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + detailModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show() + } + }, { + loadState.value = LoadState.Fail + "服务器异常".show() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt new file mode 100644 index 0000000..a0c59d8 --- /dev/null +++ b/app/src/main/java/com/casic/qd/smartwell/widgets/DetailsMarkerView.kt @@ -0,0 +1,50 @@ +package com.casic.qd.smartwell.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.qd.smartwell.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class DetailsMarkerView(context: Context?) : MarkerView(context, R.layout.popu_marker) { + private val decimalFormat = DecimalFormat("##0") + private val dayView: TextView = findViewById(R.id.dayView) + private val dataView: TextView = findViewById(R.id.dataView) + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + if (e.y == 0f) { + dataView.text = "暂无数据" + } else { + dataView.text = String.format( + Locale.CHINA, + "%s:%s件", + data, + decimalFormat.format(e.y.toDouble()) + ) + } + if (data == "阀门" || data == "水表" || data == "管线" || data == "噪声仪") { + dayView.text = String.format(Locale.CHINA, "%s年", decimalFormat.format(e.x)) + } else { + val calendar = Calendar.getInstance() + val month = calendar[Calendar.MONTH] + 1 + val day = (e.x + 1).toInt() + dayView.text = String.format(Locale.CHINA, "%d月%s日", month, day) + } + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_blue.xml b/app/src/main/res/drawable/bg_solid_layout_blue.xml new file mode 100644 index 0000000..d1dd656 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_green.xml b/app/src/main/res/drawable/bg_solid_layout_green.xml new file mode 100644 index 0000000..f600a12 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_green.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_orange.xml b/app/src/main/res/drawable/bg_solid_layout_orange.xml new file mode 100644 index 0000000..1060f2a --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_orange.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white.xml b/app/src/main/res/drawable/bg_solid_layout_white.xml new file mode 100644 index 0000000..7ecbeb8 --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml new file mode 100644 index 0000000..f00d59c --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_layout_white_radius_10.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_toast_layout.xml b/app/src/main/res/drawable/bg_toast_layout.xml new file mode 100644 index 0000000..78ff8e6 --- /dev/null +++ b/app/src/main/res/drawable/bg_toast_layout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_alarm.xml b/app/src/main/res/drawable/ic_alarm.xml new file mode 100644 index 0000000..018a29c --- /dev/null +++ b/app/src/main/res/drawable/ic_alarm.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_map.xml b/app/src/main/res/drawable/ic_home_map.xml new file mode 100644 index 0000000..2b0ae22 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_record.xml b/app/src/main/res/drawable/ic_home_record.xml new file mode 100644 index 0000000..7a1ee6c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_record.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_statistics.xml b/app/src/main/res/drawable/ic_home_statistics.xml new file mode 100644 index 0000000..a8a1ba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_statistics.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_water.xml b/app/src/main/res/drawable/ic_home_water.xml new file mode 100644 index 0000000..a91cf6e --- /dev/null +++ b/app/src/main/res/drawable/ic_home_water.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..6562ce3 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_left_white.xml b/app/src/main/res/drawable/ic_left_white.xml new file mode 100644 index 0000000..4269f97 --- /dev/null +++ b/app/src/main/res/drawable/ic_left_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..f0a5610 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_search_white.xml b/app/src/main/res/drawable/ic_search_white.xml new file mode 100644 index 0000000..5d439e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_user.xml b/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 0000000..8c4a29d --- /dev/null +++ b/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/font/sjzljt.ttf b/app/src/main/res/font/sjzljt.ttf new file mode 100644 index 0000000..ed75399 --- /dev/null +++ b/app/src/main/res/font/sjzljt.ttf Binary files differ diff --git a/app/src/main/res/layout/activity_alarm_management.xml b/app/src/main/res/layout/activity_alarm_management.xml new file mode 100644 index 0000000..5d0a0de --- /dev/null +++ b/app/src/main/res/layout/activity_alarm_management.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..f1182b8 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4a9b841 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml new file mode 100644 index 0000000..025073b --- /dev/null +++ b/app/src/main/res/layout/activity_map.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search_record.xml b/app/src/main/res/layout/activity_search_record.xml new file mode 100644 index 0000000..32c2b53 --- /dev/null +++ b/app/src/main/res/layout/activity_search_record.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..f156118 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_statistics.xml b/app/src/main/res/layout/activity_statistics.xml new file mode 100644 index 0000000..a20813b --- /dev/null +++ b/app/src/main/res/layout/activity_statistics.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml new file mode 100644 index 0000000..1649b21 --- /dev/null +++ b/app/src/main/res/layout/activity_web.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_well_detail.xml b/app/src/main/res/layout/activity_well_detail.xml new file mode 100644 index 0000000..1b47b97 --- /dev/null +++ b/app/src/main/res/layout/activity_well_detail.xml @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_base_title.xml b/app/src/main/res/layout/include_base_title.xml new file mode 100644 index 0000000..156a597 --- /dev/null +++ b/app/src/main/res/layout/include_base_title.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_empty_view.xml b/app/src/main/res/layout/include_empty_view.xml new file mode 100644 index 0000000..37de024 --- /dev/null +++ b/app/src/main/res/layout/include_empty_view.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_recycleview.xml b/app/src/main/res/layout/item_alarm_recycleview.xml new file mode 100644 index 0000000..8771a58 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_recycleview.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_home_recycleview.xml b/app/src/main/res/layout/item_home_recycleview.xml new file mode 100644 index 0000000..4130239 --- /dev/null +++ b/app/src/main/res/layout/item_home_recycleview.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/page_empty.xml b/app/src/main/res/layout/page_empty.xml new file mode 100644 index 0000000..f7351a3 --- /dev/null +++ b/app/src/main/res/layout/page_empty.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popu_marker.xml b/app/src/main/res/layout/popu_marker.xml new file mode 100644 index 0000000..5c5ab1c --- /dev/null +++ b/app/src/main/res/layout/popu_marker.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d --- /dev/null +++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d --- /dev/null +++ b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 --- /dev/null +++ b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg new file mode 100644 index 0000000..3d11f73 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/bg_home_data.jpg Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/empty.png b/app/src/main/res/mipmap-xxhdpi/empty.png new file mode 100644 index 0000000..6da1138 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/empty.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_bottom.png b/app/src/main/res/mipmap-xxhdpi/login_bottom.png new file mode 100644 index 0000000..6a4f010 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_bottom.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/login_casic.png b/app/src/main/res/mipmap-xxhdpi/login_casic.png new file mode 100644 index 0000000..edbe69a --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/login_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_background.png b/app/src/main/res/mipmap-xxhdpi/splash_background.png new file mode 100644 index 0000000..3fcca9d --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_background.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_casic.png b/app/src/main/res/mipmap-xxhdpi/splash_casic.png new file mode 100644 index 0000000..37c7e47 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_casic.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_logo.png b/app/src/main/res/mipmap-xxhdpi/splash_logo.png new file mode 100644 index 0000000..ac2ba0c --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_logo.png Binary files differ diff --git a/app/src/main/res/mipmap-xxhdpi/splash_text.png b/app/src/main/res/mipmap-xxhdpi/splash_text.png new file mode 100644 index 0000000..25684d7 --- /dev/null +++ b/app/src/main/res/mipmap-xxhdpi/splash_text.png Binary files differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp Binary files differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9126ae3 --- /dev/null +++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp Binary files differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..9ba1356 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,23 @@ + + + #1D55C6 + #333333 + #626262 + #F7F7FA + #CCCCCC + #00A000 + #FF0000 + #FF6600 + #FF8078 + #80BBFF + #96E9B5 + #916BFF + + #C0000000 + + + #FEB5A2 + #CDA5FF + #C3EB87 + #FFE1AB + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..27c04dc --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,32 @@ + + + 14sp + 16sp + 18sp + 20sp + 45sp + + + 3dp + 5dp + 7dp + 10dp + 20dp + 30dp + 50dp + 80dp + 100dp + 200dp + + + 1px + + + 56dp + + + 46dp + + + 48px + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..e3ddd7a --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,5 @@ + + QingDaoSmartWell + 中国航天科工集团 + 未知 + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..51a91d1 --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..862c02a --- /dev/null +++ b/build.gradle @@ -0,0 +1,26 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +buildscript { + ext.kotlin_version = '1.6.10' + repositories { + maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } + google() + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.6.3' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } + //依赖库 + maven { url 'https://jitpack.io' } + google() + jcenter() + } +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..831abc7 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,25 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app"s APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Kotlin code style for this project: "official" or "obsolete": +kotlin.code.style=official +# Enables namespacing of each library's R class so that its R class includes only the +# resources declared in the library itself and none from the library's dependencies, +# thereby reducing the size of the R class for that library +android.nonTransitiveRClass=true +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..e708b1c --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.jar Binary files differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..605dd40 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Thu Feb 17 13:26:46 CST 2022 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..4f906e0 --- /dev/null +++ b/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..ac1b06f --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..e7f3596 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name='QingDaoSmartWell' +include ':app'